/*
 * Operand.h
 *
 *  Created on: 2009-11-26
 *      Author: ws
 */

#ifndef OPERAND_HPP
#define OPERAND_HPP

#include<vector>
#include"common.hpp"

class Value;
class RegValue;
class ConstValue;

/*
 * the operand stand the operand in the operation which have 4 source operand and
 * one destination operand
 */

enum Opd_Type{
	SIMD_OPD,
	ADDR_OPD,
	DATA_OPD
};

class Instruction;

class Operand {
protected:
	enum Opd_Type  opd_type;
protected:
	Operand(enum Opd_Type opd_type):opd_type(opd_type)
	{
	}
public:
	enum Opd_Type get_type() const
	{
		return opd_type;
	}
	virtual void build_value(std::vector<Value*> & vs) const = 0;
	virtual bool have_a(Value * v) = 0;
	virtual ~Operand();
	friend bool operator == (Operand const &, Operand const &);
};

class SimdOperand:public Operand
{
	std::vector<RegValue*> regs;
public:
	SimdOperand(std::vector<RegValue*> values):regs(values), Operand(SIMD_OPD)
	{
	}
	std::vector<RegValue*> get_values();
	std::vector<int> get_ids()const;
	virtual bool have_a(Value *v) ;
	//TODO take account the values in the operation
	virtual void build_value(std::vector<Value *>& vs) const ;
	friend bool operator == (Operand const &, Operand const &);
	friend SimdOperand* SimdOperand_cast( Operand*);
	friend const SimdOperand* SimdOperand_cast( const Operand*);
};

class AddrOperand:public Operand
{
	Value* v;
public:
	Value * get_value();
	AddrOperand(Value *v):v(v), Operand(ADDR_OPD)
	{
	}
	virtual bool have_a(Value *v);
	virtual void build_value(std::vector<Value*>& vs ) const;
	friend bool operator == (Operand const &, Operand const &);
	friend AddrOperand* AddrOperand_cast(Operand* );
	friend const AddrOperand* AddrOperand_cast(const Operand* );
};

class DataOperand:public Operand
{
	Value * v;
public:
	DataOperand(Value *v):v(v), Operand(DATA_OPD)
	{
	}
	virtual bool have_a(Value * v);
	virtual void build_value(std::vector<Value*> &vs) const;
	Value* get_value();
	friend bool operator == (Operand const &, Operand const &);
	friend DataOperand* DataOperand_cast(Operand*);
	friend const DataOperand* DataOperand_cast(const Operand* );
};


extern AddrOperand* AddrOperand_cast(Operand* );
extern const AddrOperand* AddrOperand_cast(const Operand* );
extern DataOperand* DataOperand_cast(Operand*);
extern const DataOperand* DataOperand_cast(const Operand* );
extern SimdOperand* SimdOperand_cast( Operand*);
extern const SimdOperand* SimdOperand_cast( const Operand*);

bool operator == (Operand const & x, Operand const & y);

#endif /* DATA_H_ */
